﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web.Mvc;
using System.Web.UI;

using ProjectBase.Core;
using ProjectBase.Core.Web;
using ProjectBase.Mvc;

namespace ProjectBase.Mvc
{
    public class TreeView : VisualControl<ITreeViewModel>
    {
        #region members
        TreeViewSettings _treeViewSettings;
        string _controllerActionUrl;
        IList<string> _expandedNodes;
        #endregion members

        public TreeView(string cssClassName)
        {
            SetAttribute(Attr.Class, cssClassName);
        }
        public TreeView() { }

        protected override void BuildControls()
        {
            base.BuildControls();

            ManageState();

            if (Model.Is())
            {
                Controls.Add(CreateTreeView());
            }
        }

        protected virtual MenuHtml CreateTreeView()
        {
            var menu = new MenuHtml("treeView")
                .SetAttribute("data-nodeurl", ControllerActionUrl)
                .SetAttribute("data-tvclientid", ID)
                .AddCssClassName(GetAttribute(Attr.Class));
            menu.AddControls(CreateChildren(Model.DataSource, "treeView"));
            return menu;
        }

        #region UL, LI
        protected virtual UL CreateChildren(IEnumerable<ITVDataItem> items, string css = null)
        {
            if (items.IsEmpty())
            {
                return null;
            }
            var ul = new UL(css); // css for root

            Level++;
            foreach (var item in items)
            {
                ul.AddControls(CreateNode(item)); // children
            }
            Level--;
            return ul;
        }
        protected virtual LI CreateNode(ITVDataItem item)
        {
            var li = new LI { CreateNodeDescription(item) }; // text for this node

            if (item.Items.IsNotEmpty()) // are there children ?
            {
                var expanded = ExpandedNodes;
                if (UseDefaultSettings
                  && TreeViewSettings.LevelExpanded >= Level)
                {
                    expanded.Add(item.ID);
                }
                li.AddControls(expanded.Contains(item.ID) ? CreateChildren(item.Items) : null);
                li.SetCssClassName(expanded.Contains(item.ID) ? "ed" : "cd");
                li.SetAttribute("data-nodeid", item.ID);
            }

            return li;
        }
        #endregion UL, LI

        #region parts
        protected virtual IVisualControl CreateNodeDescription(ITVDataItem item)
        {
            var node = new PlaceHolder();
            var localized = AdjustText(item);
            var txt = localized.ToLength(TreeViewSettings.MaxTextSize ?? 50, true);

            // image
            node.AddControls
            (
                TreeViewSettings.ShowImages
                ? CreateImage(item, localized)
                : null
            );


            // text
            var literal = new Literal(txt);

            node.AddControls
            (
                (item.Href.IsEmpty() && TreeViewSettings.ShowAnchors)
                ?
                // text only
                    literal as IVisualControl
                :
                // navigation
                    new Anchor { literal }
                    .SetHref(TVCommon.CreateMvcActionUrl(item.Href, Url, item.RouteValues))
                    .SetTitle(txt.Length < localized.Length ? localized : null)
            );

            return node;
        }
        protected virtual Image CreateImage(ITVDataItem item, string txt)
        {
            // has its own declared
            if (item.ImagePath.IsNotEmpty())
            {
                return new Image(TVCommon.CreateUrl(item.ImagePath))
                    .SetAlt(txt);
            }

            // leaf
            if (item.Items.IsEmpty())
            {
                var leaf = TVCommon.CreateUrl(TreeViewSettings.ImageLeafPath ?? TVCommon.Const.ImageLeafPath);
                return new Image(leaf)
                    .SetAlt(txt);
            }

            // opened or closed
            var closed = TVCommon.CreateUrl(TreeViewSettings.ImageNodeClosedPath ?? TVCommon.Const.ImageNodeClosedPath);
            var opened = TVCommon.CreateUrl(TreeViewSettings.ImageNodeOpenedPath ?? TVCommon.Const.ImageNodeOpenedPath);
            return new Image(ExpandedNodes.Contains(item.ID) ? opened : closed)
                .SetAttribute("data-alter", ExpandedNodes.Contains(item.ID) ? closed : opened)
                .SetAlt(txt);
        }

        protected virtual string AdjustText(ITVDataItem item)
        {
            var localized = TreeViewSettings.DoLocalize
                    ? GetLocalized(item.Text)
                    : item.Text;
            if (TreeViewSettings.ShowTextWithId)
            {
                localized = item.ID
                            + (TreeViewSettings.TextWithIdSeparator ?? string.Empty)
                            + localized;
            }
            return localized;
        }
        #endregion parts

        #region properties
        /// <summary>
        ///     Set for tuning the TreeView
        /// </summary>
        public virtual TreeViewSettings TreeViewSettings
        {
            get { return _treeViewSettings ?? (_treeViewSettings = new TreeViewSettings()); }
            set { _treeViewSettings = value; }
        }

        public string ControllerActionUrl
        {
            get { return TVCommon.CreateMvcActionUrl(_controllerActionUrl, Url, null); }
            set { _controllerActionUrl = value; }

        }
        protected virtual ISessionStorage Session { get; set; }
        protected virtual int Level { get; set; }
        protected virtual bool UseDefaultSettings { get; set; }
        protected virtual IList<string> ExpandedNodes
        {
            get
            {
                if (TreeViewSettings.KeepExpandedNodesInTheSession)
                {
                    return Session[ID + TVCommon.Const.SessionKeyExpanded] as IList<string>;
                }
                return _expandedNodes;
            }
            set
            {
                if (TreeViewSettings.KeepExpandedNodesInTheSession)
                {
                    Session[ID + TVCommon.Const.SessionKeyExpanded] = value;
                    return;
                }
                _expandedNodes = value;
            }
        }
        #endregion properties

        #region State
        protected virtual void ManageState(ViewContext context = null)
        {
            if (context.Is())
            {
                var controller = context.Controller as IWebController<IViewModel>;
                var model = context.ViewData.Model as ITreeViewModel;
                if (controller.IsNull() || model.IsNull())
                {
                    throw new NullReferenceException("passed controller and model must be of a correct type IWebController<IViewModel> resp ITreeViewModel");
                }

                ViewData = new ViewDataDictionary<ITreeViewModel>(model);
                Url = controller.Url;
                ID = Model.TvClientID;
                TreeViewSettings = context.HttpContext.Application[ID] as TreeViewSettings;
                Session = context.Session();
            }
            else
            {
                ViewContext.HttpContext.Application[ID] = TreeViewSettings;
                Session = ViewContext.Session();
            }

            if (ExpandedNodes.IsNull())
            {
                UseDefaultSettings = true;
                ExpandedNodes = Model.ExpandedNodes;
            }
        }

        #endregion State
    }
}